﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BuildOptimizer
{
    class BoHatchery
    {
        //hatchery location and type
        private int _baseIndex = -1;
        private bool _isAtResources = false;

        public BoHatchery(int baseIndex, bool isAtResources)
        {
            _baseIndex = baseIndex;
            _isAtResources = isAtResources;
        }
        private BoHatchery(BoHatchery hatchery)
        {
            _baseIndex = hatchery._baseIndex;
            _isAtResources = hatchery._isAtResources;

            _isHatchery = hatchery._isHatchery;
            _isLair = hatchery._isLair;
            _isHive = hatchery._isHive;
            _isEvolving = hatchery._isEvolving;

            _isBuildingQueen = hatchery._isBuildingQueen;

            _nbLarvae = hatchery._nbLarvae;

            _timerSpawnRegularLarvae = hatchery._timerSpawnRegularLarvae;

            _isInjected = hatchery._isInjected;
            _timerSpawnInjectedLarvae = hatchery._timerSpawnInjectedLarvae;

            _nbDronesMiningMinerals = hatchery._nbDronesMiningMinerals;
            _nbDronesMovingToMinerals = hatchery.nbDronesMovingToMinerals;

            _nbDronesMiningGas = hatchery._nbDronesMiningGas;
            _nbDronesMovingToGas = hatchery._nbDronesMovingToGas;

            _nbExtractors = hatchery._nbExtractors;
        }
        public BoHatchery clone()
        {
            return new BoHatchery(this);
        }

        public int baseIndex
        {
            get
            {
                return _baseIndex;
            }
        }
        public bool isAtResources
        {
            get
            {
                return _isAtResources;
            }
        }

        //hatchery evolution
        private bool _isHatchery = true;
        private bool _isLair = false;
        private bool _isHive = false;
        private bool _isEvolving = false;
        public bool isHatchery
        {
            get
            {
                return _isHatchery;
            }
        }
        public bool isLair
        {
            get
            {
                return _isLair;
            }
        }
        public bool isHive
        {
            get
            {
                return _isHive;
            }
        }
        public bool isEvolving
        {
            get
            {
                return _isEvolving;
            }
        }
        public void makeLair()
        {
            _isEvolving = false;
            _isHatchery = false;
            _isLair = true;
            _isHive = false;
        }
        public void makeHive()
        {
            _isEvolving = false;
            _isHatchery = false;
            _isLair = false;
            _isHive = true;
        }
        public void evolveToLair()
        {
            _isEvolving = true;
        }
        public void evolveToHive()
        {
            _isEvolving = true;
        }

        //build queen
        private bool _isBuildingQueen = false;
        public bool isBuildingQueen
        {
            get
            {
                return _isBuildingQueen;
            }
        }
        public void startBuildingQueen()
        {
            _isBuildingQueen = true;
        }
        public void finishedBuildingQueen()
        {
            _isBuildingQueen = false;
        }

        //general larvae management
        private int _nbLarvae = 1;
        public int nbLarvae
        {
            get
            {
                return _nbLarvae;
            }
        }
        public void updateSpawnLarvae()
        {
            updateSpawnRegularLarvae();
            updateSpawnInjectedLarvae();

            _timerSpawnRegularLarvae = (_nbLarvae >= 3) ? 0 : _timerSpawnRegularLarvae;
            _nbLarvae = (_nbLarvae > 19) ? 19 : _nbLarvae;
        }
        public void removeLarvaeForUnit()
        {
            _nbLarvae--;
        }
        public void setLarvaeOnStartHatchery()
        {
            _nbLarvae = 3;
        }

        //spawning of regular larvae
        private int _timerSpawnRegularLarvae = 0;
        private void updateSpawnRegularLarvae()
        {
            _timerSpawnRegularLarvae++;
            if (_timerSpawnRegularLarvae == 15)
            {
                _timerSpawnRegularLarvae = 0;
                _nbLarvae++;
            }
        }

        //spawning of injected larvae
        private bool _isInjected = false;
        private int _timerSpawnInjectedLarvae = 0;
        private void updateSpawnInjectedLarvae()
        {
            if (_isInjected)
            {
                //we use 42 instead of 40 to account for the animation time of
                //a) queen injecting hatchery and b) finished larvae jumping off
                //the hatchery
                _timerSpawnInjectedLarvae++;
                if (_timerSpawnInjectedLarvae == 42)
                {
                    _timerSpawnInjectedLarvae = 0;
                    _isInjected = false;
                    _nbLarvae += 4;
                }
            }
        }
        public void inject()
        {
            _isInjected = true;
            _timerSpawnInjectedLarvae = 0;

        }
        public bool isInjected
        {
            get
            {
                return _isInjected;
            }
        }

        //mine minerals
        private int _nbDronesMiningMinerals = 0;
        private int _nbDronesMovingToMinerals = 0;
        public float newMineralsMined()
        {
            //calculate drone distribution
            int[] dronesPerPatch = { 0, 0, 0, 0, 0, 0, 0, 0 };
            for (int i = 0; i < _nbDronesMiningMinerals; i++)
            {
                int patchID = i % 8;
                dronesPerPatch[patchID]++;
            }

            //half the patches are close, the other half are further away
            //assume that close patches have more drones
            float newMinerals = 0.0f;
            for (int i = 0; i < 4; i++)
            {
                newMinerals += (dronesPerPatch[i] == 1) ? (45.0f / 60.0f) : 0.0f;
                newMinerals += (dronesPerPatch[i] == 2) ? (90.0f / 60.0f) : 0.0f;
                newMinerals += (dronesPerPatch[i] >= 3) ? (102.0f / 60.0f) : 0.0f;
            }
            for (int i = 4; i < 7; i++)
            {
                newMinerals += (dronesPerPatch[i] == 1) ? (38.0f / 60.0f) : 0.0f;
                newMinerals += (dronesPerPatch[i] == 2) ? (75.0f / 60.0f) : 0.0f;
                newMinerals += (dronesPerPatch[i] >= 3) ? (100.0f / 60.0f) : 0.0f;
            }
            return newMinerals;
        }

        //mine gas
        private int _nbDronesMiningGas = 0;
        private int _nbDronesMovingToGas = 0;
        public float newGasMined()
        {
            //calculate drone distribution
            int[] dronesPerExtractor = { 0, 0 };
            for (int i = 0; i < _nbDronesMiningGas; i++)
            {
                int extractorID = i % _nbExtractors;
                dronesPerExtractor[extractorID]++;
            }

            //mine gas
            float newGas = 0.0f;
            for (int i = 0; i < _nbExtractors; i++)
            {
                newGas += (dronesPerExtractor[i] == 1) ? (39.0f / 60.0f) : 0.0f;
                newGas += (dronesPerExtractor[i] == 2) ? (78.0f / 60.0f) : 0.0f;
                newGas += (dronesPerExtractor[i] == 3) ? (114.0f / 60.0f) : 0.0f;
            }
            return newGas;
        }

        //extractors management
        private int _nbExtractors = 0;
        public void addExtractor()
        {
            _nbExtractors++;
        }
        public int nbExtractors
        {
            get
            {
                return _nbExtractors;
            }
        }

        //drone management
        public int nbDronesMovingToMinerals
        {
            get
            {
                return _nbDronesMovingToMinerals;
            }
        }
        public int nbDronesMiningMinerals
        {
            get
            {
                return _nbDronesMiningMinerals;
            }
        }
        public int nbDronesMovingToGas
        {
            get
            {
                return _nbDronesMovingToGas;
            }
        }
        public int nbDronesMiningGas
        {
            get
            {
                return _nbDronesMiningGas;
            }
        }

        //resource gathering management
        public void moveDroneToMinerals()
        {
            _nbDronesMovingToMinerals++;
        }
        public void makeDroneMineMinerals()
        {
            _nbDronesMovingToMinerals--;
            _nbDronesMiningMinerals++;
        }
        public void removeDroneFromMiningMinerals()
        {
            _nbDronesMiningMinerals--;
        }
        public void moveDroneToGas()
        {
            _nbDronesMovingToGas++;
        }
        public void makeDroneMineGas()
        {
            _nbDronesMovingToGas--;
            _nbDronesMiningGas++;
        }
        public void removeDroneFromMiningGas()
        {
            _nbDronesMiningGas--;
        }
    }
}
